/*
 * FaceCat图形通讯框架(非开源)
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "stdafx.h"
#include "FCScrollBar.h"

namespace FaceCat{
    
    FCScrollBar::FCScrollBar(){
        m_addButton = 0;
        m_addSpeed = 0;
        m_backButton = 0;
        m_contentSize = 0;
        m_isAdding = false;
        m_isReducing = false;
        m_lineSize = 10;
        m_pageSize = 0;
        m_pos = 0;
        m_reduceButton = 0;
        m_scrollButton = 0;
        m_tick = 0;
        m_timerID = FCView::getNewTimerID();
        setDisplayOffset(false);
        FCSize size ={20, 20};
        m_size = size;
        setTopMost(true);
    }
    
    FCScrollBar::~FCScrollBar(){
        stopTimer(m_timerID);
        if (m_addButton){
            m_addButton->removeEvent((FCTouchEventCallBack*)this, L"ontouchdown");
            m_addButton->removeEvent((FCTouchEventCallBack*)this, L"ontouchup");
        }
        if (m_scrollButton){
            m_scrollButton->removeEvent((FCEventCallBack*)this, L"ondragging");
        }
        if (m_reduceButton){
            m_reduceButton->removeEvent((FCTouchEventCallBack*)this, L"ontouchdown");
            m_reduceButton->removeEvent((FCTouchEventCallBack*)this, L"ontouchup");
        }
        m_addButton = 0;
        m_backButton = 0;
        m_reduceButton = 0;
        m_scrollButton = 0;
    }
    
    FCButton* FCScrollBar::getAddButton(){
        return m_addButton;
    }
    
    int FCScrollBar::getAddSpeed(){
        return m_addSpeed;
    }
    
    void FCScrollBar::setAddSpeed(int value){
        m_addSpeed = value;
        if (m_addSpeed != 0){
            startTimer(m_timerID, 10);
        }
        else{
            stopTimer(m_timerID);
        }
    }
    
    FCButton* FCScrollBar::getBackButton(){
        return m_backButton;
    }
    
    int FCScrollBar::getContentSize(){
        return m_contentSize;
    }
    
    void FCScrollBar::setContentSize(int value){
        m_contentSize = value;
    }
    
    bool FCScrollBar::isAdding(){
        return m_isAdding;
    }
    
    void FCScrollBar::setIsAdding(bool value){
        if(m_isAdding != value){
            m_isAdding = value;
            m_tick = 0;
            if(m_isAdding){
                startTimer(m_timerID, 100);
            }
            else{
                stopTimer(m_timerID);
            }
        }
    }
    
    bool FCScrollBar::isReducing(){
        return m_isReducing;
    }
    
    void FCScrollBar::setIsReducing(bool value){
        if(m_isReducing != value){
            m_isReducing = value;
            m_tick = 0;
            if(m_isReducing){
                startTimer(m_timerID, 100);
            }
            else{
                stopTimer(m_timerID);
            }
        }
    }
    
    int FCScrollBar::getLineSize(){
        return m_lineSize;
    }
    
    void FCScrollBar::setLineSize(int value){
        m_lineSize = value;
    }
    
    int FCScrollBar::getPageSize(){
        return m_pageSize;
    }
    
    void FCScrollBar::setPageSize(int value){
        m_pageSize = value;
    }
    
    int FCScrollBar::getPos(){
        return m_pos;
    }
    
    void FCScrollBar::setPos(int value){
        m_pos = value;
        if (m_pos > m_contentSize - m_pageSize){
            m_pos = m_contentSize - m_pageSize;
        }
        if (m_pos < 0){
            m_pos = 0;
        }
    }
    
    FCButton* FCScrollBar::getReduceButton(){
        return m_reduceButton;
    }
    
    FCButton* FCScrollBar::getScrollButton(){
        return m_scrollButton;
    }
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////

    void FCScrollBar::callEvent(String eventName, Object sender, Object invoke){
         if (sender == m_scrollButton) {
             if (eventName == L"ondragging") {
                onDragScroll();
            }
        }
    }

    void FCScrollBar::callTouchEvent(String eventName, Object sender, FCTouchInfo touchInfo, Object invoke){
        if (sender == m_addButton) {
            if (eventName == L"ontouchdown") {
                onAddButtonTouchDown(touchInfo);
            } else if (eventName == L"ontouchup") {
                onAddButtonTouchUp(touchInfo);
            }
        } else if (sender == m_reduceButton) {
            if (eventName == L"ontouchdown") {
                onReduceButtonTouchDown(touchInfo);
            } else if (eventName == L"ontouchup") {
                onReduceButtonTouchUp(touchInfo);
            }
        }
    }

    ArrayList<String> FCScrollBar::getEventNames(){
        ArrayList<String> eventNames = FCView::getEventNames();
        eventNames.add(L"Scrolled");
        return eventNames;
    }
    
    String FCScrollBar::getViewType(){
        return L"ScrollBar";
    }
    
    void FCScrollBar::lineAdd(){
        m_pos += m_lineSize;
        if (m_pos > m_contentSize - m_pageSize){
            m_pos = m_contentSize - m_pageSize;
        }
        update();
        onScrolled();
    }
    
    void FCScrollBar::lineReduce(){
        m_pos -= m_lineSize;
        if (m_pos < 0){
            m_pos = 0;
        }
        update();
        onScrolled();
    }
    
    void FCScrollBar::onAddButtonTouchDown(FCTouchInfo touchInfo){
        lineAdd();
        setIsAdding(true);
    }
    
    void FCScrollBar::onAddButtonTouchUp(FCTouchInfo touchInfo){
        setIsAdding(false);
    }
    
    void FCScrollBar::onAddSpeedScrollEnd(){
        
    }
    
    void FCScrollBar::onAddSpeedScrollStart(uint64_t startTime, uint64_t nowTime, int start, int end){
        int diff = (int)((nowTime - startTime) / 100);
        if (diff > 0 && diff < 5){
            int sub = 30 * ((abs(start - end)) / 20) / diff * 10;
            //int sub = 200 * ((abs(start - end)) / 20) / diff;
            if (start > end){
                setAddSpeed(getAddSpeed() + sub);
            }
            else if (start < end){
                setAddSpeed(getAddSpeed() - sub);
            }
        }
    }
    
    int FCScrollBar::onAddSpeedScrolling(){
        int sub = m_addSpeed / 10;
        if (sub == 0){
            sub = m_addSpeed > 0 ? 1 : -1;
        }
        return sub;
    }
    
    void FCScrollBar::onDragScroll(){
        if (m_scrollButton->getLeft() < 0){
            m_scrollButton->setLeft(0);
        }
        if (m_scrollButton->getTop() < 0){
            m_scrollButton->setTop(0);
        }
        if (m_scrollButton->getRight() > m_backButton->getWidth()){
            m_scrollButton->setLeft(m_backButton->getWidth() - m_scrollButton->getWidth());
        }
        if (m_scrollButton->getBottom() > m_backButton->getHeight()){
            m_scrollButton->setTop(m_backButton->getHeight() - m_scrollButton->getHeight());
        }
    }
    
    void FCScrollBar::onLoad(){
        FCView::onLoad();
        FCHost *host = getNative()->getHost();
        if (!m_addButton){
            m_addButton = dynamic_cast<FCButton*>(host->createInternalView(this, L"addbutton"));
            m_addButton->addEvent((FCTouchEventCallBack*)this, L"ontouchdown", this);
            m_addButton->addEvent((FCTouchEventCallBack*)this, L"ontouchup", this);
            addView(m_addButton);
        }
        if (!m_backButton){
            m_backButton = dynamic_cast<FCButton*>(host->createInternalView(this, L"backbutton"));
            addView(m_backButton);
        }
        if (!m_reduceButton){
            m_reduceButton = dynamic_cast<FCButton*>(host->createInternalView(this, L"reducebutton"));
            m_reduceButton->addEvent((FCTouchEventCallBack*)this, L"ontouchdown", this);
            m_reduceButton->addEvent((FCTouchEventCallBack*)this, L"ontouchup", this);
            addView(m_reduceButton);
        }
        if (!m_scrollButton){
            m_scrollButton = dynamic_cast<FCButton*>(host->createInternalView(this, L"scrollbutton"));
            m_scrollButton->addEvent((FCEventCallBack*)this, L"ondragging", this);
            m_backButton->addView(m_scrollButton);
        }
    }
    
    void FCScrollBar::onReduceButtonTouchDown(FCTouchInfo touchInfo){
        lineReduce();
        setIsReducing(true);
    }
    
    void FCScrollBar::onReduceButtonTouchUp(FCTouchInfo touchInfo){
        setIsReducing(false);
    }
    
    void FCScrollBar::onScrolled(){
        callEvents(L"onscrolled");
        FCView *parent = getParent();
        if (parent){
            parent->invalidate();
        }
    }
    
    void FCScrollBar::onVisibleChanged(){
        FCView::onVisibleChanged();
        if(!isVisible()){
            m_pos = 0;
        }
    }
    
    void FCScrollBar::pageAdd(){
        m_pos += m_pageSize;
        if (m_pos > m_contentSize - m_pageSize){
            m_pos = m_contentSize - m_pageSize;
        }
        update();
        onScrolled();
    }
    
    void FCScrollBar::pageReduce(){
        m_pos -= m_pageSize;
        if (m_pos < 0){
            m_pos = 0;
        }
        update();
        onScrolled();
    }
    
    void FCScrollBar::scrollToBegin(){
        m_pos = 0;
        update();
        onScrolled();
    }
    
    void FCScrollBar::scrollToEnd(){
        m_pos = m_contentSize - m_pageSize;
        if(m_pos < 0){
            m_pos = 0;
        }
        update();
        onScrolled();
    }
    
    void FCScrollBar::onTimer(int timerID){
        FCView::onTimer(timerID);
        if (m_timerID == timerID){
            if (m_isAdding){
                if (m_tick > 5){
                    pageAdd();
                }
                else{
                    lineAdd();
                }
            }
            if (m_isReducing){
                if (m_tick > 5){
                    pageReduce();
                }
                else{
                    lineReduce();
                }
            }
            if (m_addSpeed != 0){
                int sub = onAddSpeedScrolling();
                setPos(getPos() + sub);
                update();
                onScrolled();
                m_addSpeed -= sub;
                if (abs(m_addSpeed) < 3){
                    m_addSpeed = 0;
                }
                if (m_addSpeed == 0){
                    onAddSpeedScrollEnd();
                    stopTimer(m_timerID);
                    if(getParent()){
                        getParent()->invalidate();
                    }
                }
            }
            m_tick++;
        }
    }
}
